package org.yx.service.smfr.save_msn_for_msn_request;

import com.fr.web.core.A.Q;
import com.xiaoleilu.hutool.collection.CollUtil;
import com.xiaoleilu.hutool.date.DateField;
import com.xiaoleilu.hutool.date.DateTime;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import org.dbist.dml.Query;
import org.yx.exception.BizException;
import org.yx.models.*;
import org.yx.service.smat.insert_material_sn_history.SmatInsertMaterialSnHistoryIn;
import org.yx.service.smat.insert_material_sn_history.SmatInsertMaterialSnHistoryService;
import org.yx.service.smat.view_material_sn.MatMsn;
import org.yx.service.smat.view_material_sn.SmatViewMaterialSnIn;
import org.yx.service.smat.view_material_sn.SmatViewMaterialSnService;
import org.yx.service.smfr.view_material_sn_waitting_for_order.MsnForWorkOrder;
import org.yx.service.smfr.view_material_sn_waitting_for_order.SmfrViewMaterialSnWaittingForOrderIn;
import org.yx.service.smfr.view_material_sn_waitting_for_order.SmfrViewMaterialSnWaittingForOrderService;
import org.yx.utils.BaseService;
import org.yx.utils.FieldMap;
import org.yx.utils.ServiceBeanUtil;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 保存工单对原材料的出入库请求
 *
 * @author zxw
 * @since 2023/03/20
 **/
public class SmfrSaveMsnForMsnRequestService extends BaseService {
    public SmfrSaveMsnForMsnRequestOut saveMsnForMsnRequest(SmfrSaveMsnForMsnRequestIn in) throws Exception {
        checkStringNotBlank(in, "mo,ioType,msn");

        /*
        SmfrViewMaterialSnWaittingForOrderIn forMoIn = new SmfrViewMaterialSnWaittingForOrderIn();
        copyProperties(in, forMoIn);
        List<MsnForWorkOrder> msnList = ServiceBeanUtil.getBean(SmfrViewMaterialSnWaittingForOrderService.class).viewMaterialSnWaittingForOrder(forMoIn).getMsnList();
        if (CollUtil.isEmpty(msnList)) {
            throw new BizException("SMFR-0017", "不允许操作原材料${msn}对于工单${mo}的本次请求。", FieldMap.of("msn", in.getMsn()), FieldMap.of("mo", in.getMo()));
        }*/

        SmatViewMaterialSnIn snIn = new SmatViewMaterialSnIn();
        snIn.setMsn(in.getMsn());
        List<MatMsn> matMsnList = ServiceBeanUtil.getBean(SmatViewMaterialSnService.class).viewMaterialSn(snIn).getMsnList();
        MatMsn matMsn = CollUtil.isEmpty(matMsnList) ? null : matMsnList.get(0);
        SmatMsnSts msnSts = matMsn == null ? null : copyProperties(matMsn, new SmatMsnSts());
        if (msnSts == null || "D".equals(msnSts.getStatus())) {
            throw new BizException("SMAT-0005", "物料批号${msn}不存在或已经被删除。", FieldMap.of("msn", in.getMsn()));
        }
        if ("H".equals(msnSts.getStatus())) {
            throw new BizException("SMAT-0006", "物料批号${msn}已经被锁定，锁定单号${holdNo}。", FieldMap.of("msn", in.getMsn()), FieldMap.of("holdNo", msnSts.getHoldNo()));
        }

        SbasMatDef matDef = selectWithPk(SbasMatDef.class, msnSts.getOrgCode(), msnSts.getMatCode(), msnSts.getMatVer());
        if (matDef == null || 'D' == matDef.getMatStatus()) {
            throw new BizException("SBAS-0002", "物料${matCode}不存在或已经删除。", FieldMap.of("matCode", msnSts.getMatCode()));
        }

        SmfrOrdDef ordDef = selectWithPk(SmfrOrdDef.class, in.getUserOrgCode(), in.getMo());
        if (ordDef == null || "D".equals(ordDef.getMoStatus())) {
            throw new BizException("SMFR-0004", "生产工单${mo}不存在或已被删除。", FieldMap.of("mo", in.getMo()));
        }

        if ("I".equals(in.getIoType())) {
            //工单退料
            if (in.getRtnQty() == null || in.getRtnQty().compareTo(BigDecimal.ZERO) < 0) {
                throw new BizException("SYS-0005", "请求的参数${parameter}要求的值${value}不正确。", FieldMap.of("parameter", "rtnQty"), FieldMap.of("value", in.getRtnQty()));
            }

            if (!"P".equals(msnSts.getStatus())) {
                throw new BizException("SMAT-0014", "物料批号${msn}当前不是生产状态。", FieldMap.of("msn", msnSts.getMsn()));
            }
            if (!in.getMo().equals(msnSts.getMo())) {
                throw new BizException("SMAT-0015", "物料批号${msn}当前不是属于生产工单${mo}。", FieldMap.of("msn", msnSts.getMsn()), FieldMap.of("mo", in.getMo()));
            }

            //保存入库
            msnSts.setStatus("I");
            msnSts.setDtlSeq(msnSts.getDtlSeq() + 1);
            msnSts.setEventCode("RETURN");
            msnSts.setEventValue(in.getMo());
            msnSts.setMo(in.getMo());
            update(msnSts, "status,dtlSeq,eventValue,eventCode,mo");

            SmatInsertMaterialSnHistoryIn historyIn = new SmatInsertMaterialSnHistoryIn();
            historyIn.setMsnSts(msnSts);
            ServiceBeanUtil.getBean(SmatInsertMaterialSnHistoryService.class).insertMaterialSnHistory(historyIn);
        } else {
            //工单领料
            if (!"I".equals(msnSts.getStatus())) {
                throw new BizException("SMAT-0011", "物料批号${msn}当前不是在库状态。", FieldMap.of("msn", msnSts.getMsn()));
            }

            if (StrUtil.isNotBlank(in.getWhCode()) && StrUtil.isNotBlank(msnSts.getWhCode()) && !StrUtil.equals(in.getWhCode(), msnSts.getWhCode())) {
                throw new BizException("SMAT-0012", "物料批号${msn}当前所在仓库${whCode}，与所请求仓库不一致。", FieldMap.of("msn", msnSts.getMsn()), FieldMap.of("whCode", msnSts.getWhCode()));
            }

            //是否是BOM物料
            Query queryBom = new Query();
            queryBom.addFilter("orgCode", ordDef.getOrgCode());
            queryBom.addFilter("prodCode", ordDef.getMatCode());
            queryBom.addFilter("prodVer", ordDef.getMatVer());
            queryBom.addFilter("matCode", msnSts.getMatCode());
            queryBom.addFilter("matVer", msnSts.getMatVer());
            queryBom.addFilter("status", "N");
            if (selectSize(SmatBomDat.class, queryBom) == 0) {
                queryBom.removeFilter("status");
                if (selectSize(SmatBomAlt.class, queryBom) == 0) {
                    throw new BizException("SMFR-0018", "物料批次${msn}物料${matCode}不在工单${mo}的BOM中。",
                            FieldMap.of("msn", msnSts.getMsn()), FieldMap.of("matCode", msnSts.getMatCode()), FieldMap.of("mo", ordDef.getMo()));
                }
            }

            if ("Y".equals(matDef.getFifoFlag())) {
                //先进先出要求
                Query query = new Query(0, 1);
                query.addFilter("orgCode", msnSts.getOrgCode());
                query.addFilter("matCode", msnSts.getMatCode());
                query.addFilter("matVer", msnSts.getMatVer());
                query.addFilter("status", "I");
                query.addFilter("qty", ">", 0);
                query.addFilter("createDate", ">=", DateUtil.date().offset(DateField.MONTH, -6));//走分区查询
                if (StrUtil.isNotBlank(in.getWhCode())) {
                    query.addFilter("whCode", in.getWhCode());
                }
                query.addOrder("supProdDate", true);
                SmatMsnSts firstMsnSts = selectOne(SmatMsnSts.class, query);
                if (firstMsnSts != null) {
                    Date currProdDate = DateUtil.parseDate(msnSts.getSupProdDate());
                    Date firstProdDate = DateUtil.parseDate(firstMsnSts.getSupProdDate());
                    if (firstProdDate.before(currProdDate)) {
                        throw new BizException("SMAT-0013", "根据物料${matCode}先进先出要求，请操作较早批次${msn}的物料。",
                                FieldMap.of("matCode", msnSts.getMatCode()), FieldMap.of("msn", firstMsnSts.getMsn()));
                    }
                }
            }

            //保存出库
            msnSts.setWhCode(null);
            msnSts.setStatus("P");
            msnSts.setDtlSeq(msnSts.getDtlSeq() + 1);
            msnSts.setEventCode("REQUEST");
            msnSts.setEventValue(in.getMo());
            msnSts.setMo(in.getMo());
            update(msnSts, "status,dtlSeq,eventValue,eventCode,mo");

            SmatInsertMaterialSnHistoryIn historyIn = new SmatInsertMaterialSnHistoryIn();
            historyIn.setMsnSts(msnSts);
            ServiceBeanUtil.getBean(SmatInsertMaterialSnHistoryService.class).insertMaterialSnHistory(historyIn);
        }

        SmfrSaveMsnForMsnRequestOut out = new SmfrSaveMsnForMsnRequestOut();
        out.setMsnSts(matMsn);

        return out;
    }
}